﻿#include "businessuser.h"

#include "businessmsghandler.h"
#include "businessviewmodel.h"
#include <AppConfig/appconfig.h>
#include <UserManager/usermanager.h>
#include "businessnetwork.h"
#include <Debug/DEBUG.hpp>
#include <SyncManager/syncmanager.h>
#include <protocol/protocolConverter.h>
#include "businesssql.h"

BusinessUser::BusinessUser() {}

void BusinessUser::initUserList(std::shared_ptr<Protocol> protocol)
{
    nlohmann::json users = BusinessMsgHandler::getJsonOfMessage(protocol);
    // init all the users
    nlohmann::json userSelf = users["User"];
    nlohmann::json friendList = users["friendMessage"];
    nlohmann::json pendingFriendList = users["pendingMessage"];
    // init the id
    AppConfig& config = AppConfig::getInstance();
    config.setRuntimeValue("UserID", std::to_string((int)userSelf["UserID"]));
    config.setRuntimeValue("Account", userSelf["Account"]);

    // init the userManager of self
    UserManager& manager = UserManager::getInstance();
    nlohmann::json& self = manager.createNewUser(userSelf["UserID"], userSelf["Account"]);
    self["Avatar"] = userSelf["Avatar"];
    // init the userManager of friend

    for (auto& user : friendList) {
        nlohmann::json& one = manager.createNewUser(user["UserID"], user["Account"]);
        one["Avatar"] = user["Avatar"];
        one["Relation"] = user["Relation"];
    }
    for (auto& user : pendingFriendList) {
        nlohmann::json& one = manager.createNewUser(user["UserID"], user["Account"]);
        one["Avatar"] = user["Avatar"];
        one["Relation"] = user["Relation"];
    }

    BusinessViewModel::getInstance().updateUserList(friendList);
    BusinessViewModel::getInstance().updateUserList(pendingFriendList);
}

void BusinessUser::replyFriendApply(QJsonObject &in, QJsonObject &out)
{
    std::string account =in["Account"].toString().toStdString();
    std::string status = in["Status"].toString().toStdString();
    UserManager& userManager = UserManager::getInstance();
    uint64_t userID = std::stoi(AppConfig::getInstance().runtimeValue("UserID"));
    DEBUG_INFO(account);
    User& targetUser = userManager.getTargetUser(account);

    DEBUG_INFO(targetUser.dump());

    int subType = 8;
    if (status == "accept") {
        subType = 7;
    }

    BusinessNetWork::getInstance().sendMessageToServer(2, subType , userID, targetUser["UserID"], 0,
                                                       nullptr, 0);
}

void BusinessUser::applyAddFriend(QJsonObject &in, QJsonObject &out)
{
    std::string targetAccount = in["targetAccount"].toString().toStdString();

    UserManager& userManager = UserManager::getInstance();
    uint64_t selfID = std::stoi(AppConfig::getInstance().runtimeValue("UserID"));

    BusinessNetWork::getInstance().sendMessageToServer(2, 1 , selfID, 0, 0,
                                                       (unsigned char*)targetAccount.c_str(), targetAccount.size());

}

void BusinessUser::applyForRefreshUserList(QJsonObject &in, QJsonObject &out)
{
    std::string Account = AppConfig::getInstance().runtimeValue("Account");
    BusinessNetWork::getInstance().sendMessageToServer(2, 9, 0, 0, 0,
                                                       (unsigned char *)Account.c_str(), Account.size());
}

User &BusinessUser::getTargetUser(const std::string &account)
{
    // if not exist , request to server
    UserManager& userManager = UserManager::getInstance();

    if (userManager.isExist(account)) {
        // if exist user
        return userManager.getTargetUser(account);
    }
    // if not exist

    SyncManager& syncManager = SyncManager::getInstance();
    SyncPoint point = syncManager.generateUniqueSyncPoint();
    uint64_t UserID = std::stoi(AppConfig::getInstance().runtimeValue("UserID"));
    // wait for server reply
    BusinessNetWork::getInstance().sendMessageToServer(2, 10, UserID, 0, point,
                                                       (unsigned char *)account.c_str(), account.size());

    syncManager.waitForSyncPoint(point);

    return userManager.getTargetUser(account);
}

User& BusinessUser::getTargetUser(uint64_t id) {
    // if not exist , request to server
    UserManager& userManager = UserManager::getInstance();

    User& targetUser = userManager.getTargetUser(id);
    if (!targetUser.empty()) {
        // if exist user
        return targetUser;
    }
    // if not exist

    SyncManager& syncManager = SyncManager::getInstance();
    SyncPoint point = syncManager.generateUniqueSyncPoint();
    uint64_t UserID = std::stoi(AppConfig::getInstance().runtimeValue("UserID"));
    // wait for server reply
    BusinessNetWork::getInstance().sendMessageToServer(2, 10, UserID, id, point,
                                                       nullptr, 0);

    syncManager.waitForSyncPoint(point);

    targetUser = UserManager::getInstance().getTargetUser(id);
    return targetUser;
}

void BusinessUser::eraseFriend(QJsonObject &in, QJsonObject &out)
{
    QString QtargetAccount = in["targetAccount"].toString();

    uint64_t selfID = std::stoi(AppConfig::getInstance().runtimeValue("UserID"));
    User& targetUser = getTargetUser(QtargetAccount.toStdString());
    uint64_t targetID = targetUser["UserID"];

    BusinessNetWork::getInstance().sendMessageToServer(2, 3,
                                                       selfID, targetID, 0,
                                                       nullptr, 0);

}

void BusinessUser::addUser(std::shared_ptr<Protocol> protocol)
{
    User user = BusinessMsgHandler::getJsonOfMessage(protocol);
    DEBUG_INFO(user.dump());
    UserManager& manager = UserManager::getInstance();

    uint64_t id = user["UserID"];
    std::string account = user["Account"];

    DEBUG_INFO("id: " + std::to_string(id) + " account: " + account);

    nlohmann::json& one = manager.createNewUser(id, account);
    one["Avatar"] = user["Avatar"];
    one["Relation"] = user["Relation"];

    DEBUG_INFO("user3 accountID: " + std::to_string(manager.account2ID(account)));

    AppConfig& config = AppConfig::getInstance();

    ProtocolConverter converter;
    converter.setProtocolOption(BusinessNetWork::getInstance().getProtocolOption());
    converter.parseData((unsigned char *)protocol->data());

    uint64_t point = std::get<int64_t>(converter.getHeaderField(4));

    DEBUG_INFO(account + " add user : " + UserManager::getInstance().getTargetUser(account).dump());

    SyncManager::getInstance().releaseSyncPoint(point, true);
}

void BusinessUser::updateLocalMessage(QJsonObject &in, QJsonObject &out)
{
    std::string targetAccount = in["targetAccount"].toString().toStdString();

    User& targetUser = getTargetUser(targetAccount);

    uint64_t receiverID = targetUser["UserID"];
    uint64_t selfID = std::stoi(AppConfig::getInstance().runtimeValue("UserID"));


    auto messages = BusinessSQL::getInstance().queryLatest20UserMessage(selfID, receiverID);

    for (auto&i : messages) {
        uint64_t senderID = i["SenderID"];
        if (senderID == selfID) {
            BusinessViewModel::getInstance().addMessageFromSelf(targetUser, i["Message"], i["MessageType"], i["Time"]);
        } else {
            BusinessViewModel::getInstance().addMessageFromUser(targetUser, i["Message"], i["MessageType"], i["Time"]);
        }
    }

}

void BusinessUser::updateAvatar(QJsonObject &in, QJsonObject &out)
{
    int targetAvatar = in["Avatar"].toInt();

    uint64_t selfID = std::stoi(AppConfig::getInstance().runtimeValue("UserID"));

    User& user = BusinessUser::getInstance().getTargetUser(selfID);
    user["Avatar"] = targetAvatar;

    BusinessNetWork::getInstance().sendMessageToServer(2, 17,
                                                       selfID, targetAvatar, 0,
                                                       nullptr, 0);

}
